﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LeadExpress.Models;
using LeadExpress.Models.ViewPages;
using System.Data;

namespace LeadExpress.Repository
{
    public class ProductTransactionManagementRepository : BaseManagementRepository
    {
        LeadExpressEntities entities = new LeadExpressEntities();

        public ProductTransactionManagementModel GetModel(string pageType, 
            string roleName, 
            string keywords, 
            string startDate,
            string endDate,
            string[] optionId,
            string[] paymentId,
            string sortBy,
            string sortOrder,
            int pageSize,
            int pageIndex,
            int id)
        {
            // Update status
            if (id > 0)
            {
                Delete(id);
            }

            // Set value
            ProductTransactionManagementModel model = new ProductTransactionManagementModel();
            int totalRecord = 0;
            model.ListProductTransaction = GetAll(keywords, startDate, endDate, optionId, paymentId, sortBy, sortOrder, pageSize, pageIndex, ref totalRecord);
            PaginateModel paging = new PaginateModel();

            if (totalRecord > 0)
            {
                paging.PageIndex = pageIndex;
                paging.PageSize = pageSize;
                paging.TotalRecords = totalRecord;
                paging.TotalPages = (totalRecord % pageSize == 0) ? (totalRecord / pageSize) : (totalRecord / pageSize + 1);
            }
            else
            {
                paging.PageIndex = 1;
                paging.PageSize = 10;
                paging.TotalRecords = 0;
                paging.TotalPages = 1;
            }
            model.Paging = paging;

            if (id > 0)
            {
                model.ProductTransactionInfo = GetSingle(id);
            }

            return model;
        }

        public ProductTransactionManagementModel GetModel(string pageType, string roleName, int pageSize, int pageIndex)
        {
            ProductTransactionManagementModel model = new ProductTransactionManagementModel();
            int totalRecord = 0;

            model.HeaderView = GetHeader();
            model.MenuItem = GetMenuItems(roleName, pageType);
            model.ListProductTransaction = GetAll(string.Empty, pageSize, pageIndex, ref totalRecord);
            PaginateModel paging = new PaginateModel();

            if (totalRecord > 0)
            {
                paging.PageIndex = pageIndex;
                paging.PageSize = pageSize;
                paging.TotalRecords = totalRecord;
                paging.TotalPages = (totalRecord % pageSize == 0) ? (totalRecord / pageSize) : (totalRecord / pageSize + 1);
            }
            else
            {
                paging.PageIndex = 1;
                paging.PageSize = 10;
                paging.TotalRecords = 0;
                paging.TotalPages = 1;
            }
            model.Paging = paging;

            // Add Options
            model.ListProductOption = new Repository.ProductOptionManagementRepository().GetAllItems();
            model.ListProductGroup = new Repository.ProductGroupManagementRepository().GetAllItems();
            model.ListPaymentMethod = new Repository.PaymentManagementRepository().GetAll(true);
            model.ListRangeTime = GetRange();

            return model;
        }

        public ProductTransactionManagementModel GetModel(string pageType, string roleName, int id)
        {
            ProductTransactionManagementModel model = new ProductTransactionManagementModel();

            model.HeaderView = GetHeader();
            model.MenuItem = GetMenuItems(roleName, pageType);
            model.ProductTransactionInfo = GetSingle(id);

            // Add Options
            model.ListProductOption = new Repository.ProductOptionManagementRepository().GetAllItems();
            model.ListProductGroup = new Repository.ProductGroupManagementRepository().GetAllItems();
            model.ListPaymentMethod = new Repository.PaymentManagementRepository().GetAll(true);

            return model;
        }

        #region #Private functions
        private List<OptionModel> GetRange()
        {
            List<OptionModel> list = new List<OptionModel>();

            OptionModel model;
            model = new OptionModel { ID = DateTime.Now.ToString("MM/dd/yyyy") + "|" + DateTime.Now.ToString("MM/dd/yyyy"), Name = "Hôm nay" };
            list.Add(model);

            model = new OptionModel { ID = DateTime.Now.AddDays(-1).ToString("MM/dd/yyyy") + "|" + DateTime.Now.AddDays(-1).ToString("MM/dd/yyyy"), Name = "Hôm qua" };
            list.Add(model);

            model = new OptionModel { ID = DateTime.Now.AddDays(-7).ToString("MM/dd/yyyy") + "|" + DateTime.Now.ToString("MM/dd/yyyy"), Name = "7 ngày trước" };
            list.Add(model);

            model = new OptionModel { ID = DateTime.Now.AddDays(-30).ToString("MM/dd/yyyy") + "|" + DateTime.Now.ToString("MM/dd/yyyy"), Name = "30 ngày trước" };
            list.Add(model);

            DateTime startDate = new DateTime();
            DateTime endDate = new DateTime();

            // before this month
            startDate = Utility.LeadTools.GetFirstDayOfMonth(DateTime.Now.Month - 1, DateTime.Now.Year);
            endDate = Utility.LeadTools.GetLastDayOfMonth(startDate);
            model = new OptionModel { ID = startDate.ToString("MM/dd/yyyy") + "|" + endDate.ToString("MM/dd/yyyy"), Name = "Tháng trước" };
            list.Add(model);

            // before 2 month
            startDate = Utility.LeadTools.GetFirstDayOfMonth(DateTime.Now.Month -2, DateTime.Now.Year);
            endDate = Utility.LeadTools.GetLastDayOfMonth(startDate.AddMonths(1));
            model = new OptionModel { ID = startDate.ToString("MM/dd/yyyy") + "|" + endDate.ToString("MM/dd/yyyy"), Name = "2 tháng trước" };
            list.Add(model);

            // Before 3 month
            startDate = Utility.LeadTools.GetFirstDayOfMonth(DateTime.Now.Month -3, DateTime.Now.Year);
            endDate = Utility.LeadTools.GetLastDayOfMonth(startDate.AddMonths(2));
            model = new OptionModel { ID = startDate.ToString("MM/dd/yyyy") + "|" + endDate.ToString("MM/dd/yyyy"), Name = "3 tháng trước" };
            list.Add(model);

            // This month
            startDate = Utility.LeadTools.GetFirstDayOfMonth(DateTime.Now.Month, DateTime.Now.Year);
            endDate = Utility.LeadTools.GetLastDayOfMonth(startDate);
            model = new OptionModel { ID = startDate.ToString("MM/dd/yyyy") + "|" + endDate.ToString("MM/dd/yyyy"), Name = "Tháng này" };
            list.Add(model);

            // All time
            model = new OptionModel { ID = "-1", Name = "Tất cả" };
            list.Add(model);

            return list;
        }

        private List<ProductTransactionModel> GetAll(string keywords, string startDate, string endDate, string[] optionId, string[] paymentId, string sortBy, string sortOrder, int pageSize, int pageIndex, ref int total)
        {
            List<ProductTransactionModel> list = new List<ProductTransactionModel>();
            List<int> arrOption = new List<int>();
            List<int> arrGroup = new List<int>();
            List<int> arrPayment = new List<int>();

            var banners = (from c in entities.ProductTransactions
                           select c);

            // Option list
            if (optionId.Length > 0 && int.Parse(optionId[0]) > 0)
            {
                for (int i = 0; i < optionId.Length; i++)
                {
                    arrOption.Add(int.Parse(optionId[i]));
                }
                banners = banners.Where(c => arrOption.Contains(c.OptionID.Value));
            }

            // Payment list
            if (paymentId.Length > 0 && int.Parse(paymentId[0]) > 0)
            {
                for (int i = 0; i < paymentId.Length; i++)
                {
                    arrPayment.Add(int.Parse(paymentId[i]));
                }
                banners = banners.Where(c => arrPayment.Contains(c.PaymentID.Value));
            }

            // Check conditions
            if (!string.IsNullOrEmpty(keywords))
                banners = banners.Where(c => c.ProductName.Contains(keywords));

            DateTime isStartDate;
            if (!string.IsNullOrEmpty(startDate) && DateTime.TryParse(startDate, out isStartDate))
            {
                DateTime sDate = Convert.ToDateTime(startDate);
                banners = banners.Where(c => c.DateCreated >= sDate);
            }
            DateTime isEndDate;
            if (!string.IsNullOrEmpty(endDate) && DateTime.TryParse(endDate, out isEndDate))
            {
                DateTime eDate = Convert.ToDateTime(endDate);
                banners = banners.Where(c => c.DateCreated <= eDate);
            }
            
            // Get total count
            try
            {
                if (banners != null && banners.Count() > 0)
                {
                    total = banners.Count();
                    List<ProductTransaction> listTemp = new List<ProductTransaction>();

                    // Sort by Column|Order
                    sortOrder = sortOrder.ToUpper();
                    sortBy = sortBy.ToUpper();
                    switch (sortBy)
                    {
                        case "NAME":
                            {
                                if(sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.ProductName).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.ProductName).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "PRICE":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.ListPrice).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.ListPrice).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "UNITPRICE":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.UnitPrice).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.UnitPrice).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "STARTDATE":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.StartDate).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.StartDate).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "ENDDATE":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.EndDate).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.EndDate).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "DATECREATED":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.DateCreated).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.DateCreated).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        case "APPROVED":
                            {
                                if (sortOrder == "ASC")
                                    listTemp = banners.OrderBy(c => c.Approved).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.Approved).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                        default:
                            {
                                if(sortOrder == "ASC")
                                    listTemp = banners.OrderByDescending(c => c.DateCreated).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                else
                                    listTemp = banners.OrderByDescending(c => c.DateCreated).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                                break;
                            }
                    } 
            
                    // Add all item to list
                    foreach (var item in listTemp)
                    {
                        ProductTransactionModel model = new ProductTransactionModel();

                        // Transaction info
                        model.ID = item.ID;
                        model.ProductName = item.ProductName;
                        model.StartDate = Convert.ToDateTime(item.StartDate).ToString("dd-MM-yyyy");
                        model.EndDate = Convert.ToDateTime(item.EndDate).ToString("dd-MM-yyyy");
                        model.ListPrice = Convert.ToDouble(item.ListPrice).ToString("#,###").Replace(",", ".");
                        model.UnitPrice = item.UnitPrice;
                        model.DateCreated = Convert.ToDateTime(item.DateCreated).ToString("dd-MM-yyyy hh:mm tt"); ;
                        model.Approved = item.Approved;
                        list.Add(model);
                    }
                }
            }
            catch (Exception ex)
            {
                Helpers.ErrorHandle.AddError(ex.Message);
            }

            return list;
        }

        private List<ProductTransactionModel> GetAll(string keywords, int pageSize, int pageIndex, ref int total)
        {
            List<ProductTransactionModel> list = new List<ProductTransactionModel>();
            var banners = (from c in entities.ProductTransactions
                           select c);

            // Check conditions
            if (!string.IsNullOrEmpty(keywords))
                banners = banners.Where(c => c.ProductName.Contains(keywords));
            
            // Get total count
            total = banners.Count();
            var items = banners.OrderByDescending(c => c.DateCreated).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize);
            
            // Add all item to list
            foreach (var item in items)
            {
                ProductTransactionModel model = new ProductTransactionModel();

                // Transaction info
                model.ID = item.ID;
                model.ProductName = item.ProductName;
                model.StartDate = Convert.ToDateTime(item.StartDate).ToString("dd-MM-yyyy");
                model.EndDate = Convert.ToDateTime(item.EndDate).ToString("dd-MM-yyyy");
                model.ListPrice = Convert.ToDouble(item.ListPrice).ToString("#,###").Replace(",", ".");
                model.UnitPrice = item.UnitPrice;
                model.DateCreated = Convert.ToDateTime(item.DateCreated).ToString("dd-MM-yyyy hh:mm tt"); ;
                model.Approved = item.Approved;

                list.Add(model);
            }

            return list;
        }

        private bool IsExist(string[] arr, int? id)
        {
            bool isExist=false;

            for(int i=0;i<arr.Length;i++)
            {
                if(int.Parse(arr[i]) == id)
                {
                    isExist=true;
                    break;
                }
            }

            return isExist;
        }
        #endregion

        #region Reference function
        private List<ProductTransaction> GetAll()
        {
            return (from c in entities.ProductTransactions
                    orderby c.TransactionDate
                    select c).ToList();
        }


        public ProductTransaction GetSingleByProduct(int id)
        {
            return (from _object in entities.ProductTransactions
                    where _object.ProductID == id
                    orderby _object.ID descending
                    select _object).FirstOrDefault();
        }

        public ProductTransaction GetSingle(int id)
        {
            return (from _object in entities.ProductTransactions where _object.ID == id select _object).FirstOrDefault();
        }
        
        public void Create([Bind(Exclude = "ID, DateCreated")] ProductTransaction _object)
        {
            _object.DateCreated = System.DateTime.Now;
            entities.AddToProductTransactions(_object);
            entities.SaveChanges();
        }

        public void Delete(int id)
        {
            var _object = (from _list in entities.ProductTransactions where _list.ID == id select _list).First();
            entities.DeleteObject(_object);
            entities.SaveChanges();
        }

        public void Update(ProductTransaction _object)
        {
            //_object.DateCreated = System.DateTime.Now;
            entities.SaveChanges();
        }

        public void Save([Bind(Exclude = "ID")] ProductTransaction _object)
        {
            _object.EntityKey = (from ProductTransaction ac in entities.ProductTransactions where ac.ID == _object.ID select ac).FirstOrDefault().EntityKey;
            _object.DateCreated = System.DateTime.Now;
            entities.SaveChanges();
        }
        #endregion

        #region #reports

        public FileResult ExportToCSVFile()
        {
            var list = GetAll();
            DataTable dt = CreateDataTableReturnLeads(list);
            return CreateCSVFile(dt, "BT");
        }

        private static DataTable CreateDataTableReturnLeads(List<ProductTransaction> data)
        {
            // Here we create a DataTable with columns.
            DataTable table = new DataTable();
            table.Columns.Add("Tên bản tin rao vặt", typeof(string));
            table.Columns.Add("Thanh toán", typeof(string));
            table.Columns.Add("Từ ngày", typeof(string));
            table.Columns.Add("Đến ngày", typeof(string));
            table.Columns.Add("Giá", typeof(string));
            table.Columns.Add("Đơn vị tính", typeof(string));
            table.Columns.Add("Ngày giao dịch", typeof(string));

            // Here we add DataRows.
            if (data.Count > 0)
            {
                foreach (var item in data)
                {
                    table.Rows.Add(
                        item.ProductName,
                        item.PaymentName,
                        item.StartDate,
                        item.EndDate,
                        item.ListPrice,
                        item.UnitPrice
                        );
                }
            }
            return table;
        }

        #endregion
    }
}
